<?php
/**
 * Date: 2024.8
 * Author: kahn
 */
namespace service\uc;

use cache\JwtCache;
use config\Response;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class JwtService{

    /**
     * 生成jwt
     * @param $userId
     * @return string|null
     */
    static function generateJWT($userId){
        $jwtConfig = \Yaf_Registry::get("config")->jwt;
        $cur = time();
        $payload = [
            'sub' => $userId,
            'iat' => $cur,
            'expire' => $cur + $jwtConfig->exp,
        ];

        $jwt = JWT::encode($payload, $jwtConfig->key, 'HS256');
        $refreshToken = md5($jwt. $cur);

        if(!(new JwtCache())->setRefreshToken($userId, $refreshToken, $jwtConfig->refresh_exp)){
            return null;
        }

        $jwt = "$jwt $refreshToken";

        return $jwt;
    }

    /**
     * jwt验证
     * @param $userId
     * @param $newJwt
     * @return int
     */
    static function verifyJwt(&$userId, &$newJwt): int
    {
        $userId = 0;
        $jwt = $_SERVER['HTTP_AUTHORIZATION'] ?? null;
        if(!$jwt){
            return Response::JWT_ERROR;
        }
        $jwtArr = explode(' ', $jwt);
        if(count($jwtArr) != 3){
            return Response::JWT_ERROR;
        }
        try{
            $payload = JWT::decode($jwtArr[1], new Key(\Yaf_Registry::get("config")->jwt->key, 'HS256'));
            $userId = $payload->sub;
            $expire = $payload->expire;
            if($expire <= time()){ //jwt过期
                $refreshToken = (new JwtCache())->getRefreshToken($userId);
                if($refreshToken == $jwtArr[2]){ //refresh token验证成功, 刷新jwt
                    $newJwt = self::generateJWT($userId);
                    if($newJwt){
                        return Response::JWT_EXPIRE;
                    }else{ //如果生成新的token失败
                        return Response::SYSTEM_ERROR;
                    }
                }else{ //refresh token不匹配, 验证失败
                    return Response::JWT_ERROR;
                }
            }else{  //jwt验证成功
                return Response::SUCCESS;
            }
        }catch (\Exception $e){ //jwt解析失败
            return Response::JWT_ERROR;
        }
    }

}